package com.ndp.fb.walle.config.json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.PropertyPreFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by infi.he on 2016/3/17.
 */
public class ComplexPropertyPreFilter implements PropertyPreFilter {

    private Map<Class<?>, String[]> includes = new HashMap<>();

    static {
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }

    public boolean apply(JSONSerializer serializer, Object source, String name) {

        if (source == null) {
            return true;
        }

        Class<?> clazz = source.getClass();

        if (this.includes.isEmpty()) {
            return true;
        }

        if (!this.includes.containsKey(clazz)){
            return true;
        }

        // 需要序列的对象
        // 找到不需要的序列化的类型
        for (Map.Entry<Class<?>, String[]> item : this.includes.entrySet()) {
            // isAssignableFrom()，用来判断类型间是否有继承关系
            if (item.getKey().isAssignableFrom(clazz)) {
                String[] strs = item.getValue();
                // 该类型下 此 name 值无需序列化
                if (isHave(strs, name)) {
                    return true;
                }
            }
        }
        return false;
    }

    /*
     * 此方法有两个参数，第一个是要查找的字符串数组，第二个是要查找的字符或字符串
     */
    public static boolean isHave(String[] strs, String s) {
        for (int i = 0; i < strs.length; i++) {
            if (strs[i].equals(s)) {
                return true;
            }
        }
        return false;
    }

    public Map<Class<?>, String[]> getIncludes() {
        return includes;
    }

    public void setIncludes(Map<Class<?>, String[]> includes) {
        this.includes = includes;
    }

    public void addIncludes(Class clazz, String... includes) {
        String[] strings = this.includes.get(clazz);
        if (strings == null) {
            this.includes.put(clazz, includes);
        } else {
            String[] dest = new String[strings.length + includes.length];
            System.arraycopy(strings, 0, dest, 0, strings.length);
            System.arraycopy(includes, 0, dest, strings.length, includes.length);
        }
    }
}
